﻿/* ***************************************************************************************
 * Linq To SystemSearch
 * 
 *
 * This is an example of how extend LinQ using IQueruable and IOrderedQuerable interfaces.
 * 
 * User this code as you want,  is free.
 * 
 * Develop by: Mario Rodriguez
 * email: marior666@hotmail.com
 * 
 ********************************************************************************************/


using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Linq.Expressions;
using System.Diagnostics;

namespace System.Search.Linq
{
    [DebuggerVisualizer(typeof(SystemIndexListQueryVisualizer))]
    [Serializable]
    class SystemIndexListQuery<T> : IOrderedQueryable<T>, ISerializable
    {
        [NonSerialized]
        private Expression expression;
        
        SystemIndexContext context;
        
        Query<T> query;

        private Query<T> Query
        {

            get
            {
                if (query == null)
                    query = context.ExecuteQuery<T>(expression);
                return query;
            }
            set
            {
                query = value;
            }
        }

        string expressionStr;

        private string ExpressionStr
        {

            get
            {
                if (expressionStr == null)
                    expressionStr = expression.ToString();
                return expressionStr;
            }
            set
            {
                expressionStr = value;
            }
        }


        public SystemIndexListQuery(SystemIndexContext c, Expression e)
        {
            expression = e;
            context = c;

        }


        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator()
        {
            return context.Execute<T>(expression);
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IQueryable Members

        public Type ElementType
        {
            get { return typeof(T); }
        }

        public System.Linq.Expressions.Expression Expression
        {
            get { return expression; }
        }

        public IQueryProvider Provider
        {
            get { return new SystemIndexQueryProvider<T>(context); }
        }

        #endregion

        #region ISerializable Members

        /// <summary>
        /// Constructor to support debugger visualizers. Not for direct use in end-user code.
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        /// <remarks>Query parser refactorings should allow to move this to another 'SystemIndexQuery' class level at a later stage.</remarks>
        public SystemIndexListQuery(SerializationInfo info, StreamingContext context)
        {
            this.context = (SystemIndexContext)info.GetValue("context", typeof(SystemIndexContext));
            this.Query = (Query<T>)info.GetValue("query", typeof(Query<T>));
            this.expressionStr = info.GetString("expressionStr");
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {

            Query = this.context.ExecuteQuery<T>(expression);
          
            info.AddValue("context", this.context);
            info.AddValue("query", this.Query);
            info.AddValue("expressionStr",ExpressionStr);


        }

        #endregion
    }
}
